package com.example.silang.befoolishble;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.telecom.Log;
import android.view.View;

import java.util.AbstractSequentialList;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

public class MainActivity extends AppCompatActivity {
    private BluetoothAdapter mBluetoothAdapter;
    UUID[] serviceUuids;
    String devideMac;
    MyBleScanCallback mMyBleScanCallback;

    MyBluetoothGattCallback mMyBluetoothGattCallback;
    private UUID serviceUuid;
    private BluetoothGattService discoverService;  //目标服务
    private BluetoothGatt discoverBluetoothGatt;
    private BluetoothGatt readWriteBluetoothGatt;
    private UUID charecterUUid;
    private String sendvalue;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        // Initializes Bluetooth adapter.
        final BluetoothManager bluetoothManager =
                (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        mBluetoothAdapter = bluetoothManager.getAdapter();
        mMyBleScanCallback =  new MyBleScanCallback(devideMac);
    }

    public void click(View view) {

        switch (view.getId()) {


            case R.id.checkOpen://检测打开
                checkBlutooth(mBluetoothAdapter);



            case R.id.scan://扫描
                startScanf( mBluetoothAdapter,serviceUuids, mMyBleScanCallback);
                break;

            case R.id.connect://链接
                connectBle(mMyBleScanCallback.targetDevice,this,true,mMyBluetoothGattCallback);
                break;


            case R.id.discoverService://发现服务
                discoverService(discoverBluetoothGatt,serviceUuid);

                break;

            case R.id.writeData://写数据
                writeBleData(readWriteBluetoothGatt,serviceUuid,charecterUUid,sendvalue);
                break;
//
//            case R.id.scan:
//                break;


        }

    }



    //TODO 如果检测到蓝牙没有开启，尝试开启蓝牙
    private void checkBlutooth(BluetoothAdapter mBluetoothAdapter) {
        int REQUEST_ENABLE_BT = 100;
        // Ensures Bluetooth is available on the device and it is enabled. If not,
        // displays a dialog requesting user permission to enable Bluetooth.
        if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
            Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
        }
    }


    /***
     * 扫描蓝牙设备
     * @param mBluetoothAdapter
     * @param serviceUuids
     * @param callback
     */
    private void startScanf(BluetoothAdapter mBluetoothAdapter, UUID[] serviceUuids,
                            BluetoothAdapter.LeScanCallback callback) {

        if (mBluetoothAdapter == null || callback == null) {
            return;
        }

        if (serviceUuids != null && serviceUuids.length > 0) {
            mBluetoothAdapter.startLeScan(serviceUuids, callback);
        } else {
            mBluetoothAdapter.startLeScan(callback);
        }

    }


    /***
     * 停止扫描
     * @param mBluetoothAdapter
     * @param callback   传入的回调必须是开启蓝牙扫描时传入的回调，否则蓝牙扫描不会停止
     */
    private void stopBleScan(BluetoothAdapter mBluetoothAdapter, BluetoothAdapter.LeScanCallback callback) {
        if (mBluetoothAdapter == null || callback == null) {
            return;
        }

        mBluetoothAdapter.stopLeScan(callback);
    }


    private class MyBleScanCallback implements BluetoothAdapter.LeScanCallback {

        //private List<BluetoothDevice> bluetoothDeviceArrayList = new ArrayList<>();

        private String mac;
        private BluetoothDevice targetDevice;

        public MyBleScanCallback(String mac){ //根据Mac 地址识别设备
            this.mac = mac;
        }

        public BluetoothDevice getTargetDevice() {
            return targetDevice;
        }

        //        public List<BluetoothDevice> getBluetoothDeviceArrayList() {
//            return bluetoothDeviceArrayList;
//        }

        /***
         *一旦发现蓝牙设备，LeScanCallback 就会被回调，直到 stopLeScan 被调用。
         * 出现在回调中的设备会重复出现，所以如果我们需要通过 BluetoothDevice 获取外围设备的地址手动过滤掉已经发现的外围设备
         *
         * @param device 代表蓝牙设备的类，可以通过这个类建立蓝牙连接获取关于这一个设备的一系列详细的参数，例如名字，MAC 地址等等
         * @param rssi 蓝牙的信号强弱指标，通过蓝牙的信号指标，可以大概计算出蓝牙设备离手机的距离。计算公式为：d = 10^((abs(RSSI) - A) / (10 * n))
         * @param scanRecord  蓝牙广播出来的广告数据
         */
        @Override
        public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {

            if(device.getAddress().equals(mac)){
                targetDevice = device;
            }
           // bluetoothDeviceArrayList.add(device);

        }

    }

    private void  discoverService(BluetoothGatt mBluetoothGatt,UUID serviceuuId){
        mBluetoothGatt.discoverServiceByUuid(serviceuuId);
    }

    /**
     * 连接蓝牙设备
     *
     * @param device
     * @param context
     * @param autoConnect
     * @param callback
     */
    private void connectBle(BluetoothDevice device, Context context, boolean autoConnect,
                            BluetoothGattCallback callback) {
        device.connectGatt(context, autoConnect, callback);
    }

    /**
     * 例如连接和断开连接的回调，发现服务的回调，成功写入数据，成功读取数据的回调等等。
     */
    private class MyBluetoothGattCallback extends BluetoothGattCallback {


        /****
         * onConnectionStateChang 方法被成功回调且表示成功连接之后调用这一个方法。
         * 当这一个方法被调用之后，系统会异步执行发现服务的过程，
         * 直到 BluetoothGattCallback#onServicesDiscovered 被系统回调之后，
         * 手机设备和蓝牙设备才算是真正建立了可通信的连接。
         * @param gatt
         * @param status
         */
        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            super.onServicesDiscovered(gatt, status);
            discoverService = gatt.getService(serviceUuid);
            
            readWriteBluetoothGatt = gatt;

        }

        /****
         * 读取数据回调
         * @param gatt
         * @param characteristic
         * @param status
         */
        @Override
        public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            super.onCharacteristicRead(gatt, characteristic, status);

            Log.d("BLE", status == BluetoothGatt.GATT_SUCCESS ? "读取数据成功！！" : "读取数据失败！！");
        }


        /***
         * 数据写回调
         * @param gatt
         * @param characteristic
         * @param status
         */
        @Override
        public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic,
                                          int status) {
            super.onCharacteristicWrite(gatt, characteristic, status);
            Log.d("BLE", status == BluetoothGatt.GATT_SUCCESS ? "写数据成功！！" : "写数据失败！！");
        }


        /***
         *链接或者断开链接回调
         * @param gatt   蓝牙设备的 Gatt 服务连接类
         * @param status  是否成功执行了连接操作，如果为 BluetoothGatt.GATT_SUCCESS 表示成功执行连接操作，
         *                第三个参数才有效，否则说明这次连接尝试不成功
         * @param newState  当前设备的连接状态，如果 newState == BluetoothProfile.STATE_CONNECTED 说明设备已经连接，
         *                  可以进行下一步的操作了-----发现蓝牙服务。
         *                  当蓝牙设备断开连接时，这一个方法也会被回调，
         *                  其中的 newState == BluetoothProfile.STATE_DISCONNECTED。
         */
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status,
                                            int newState) {
            Log.d("Ble", "onConnectionStateChange: thread "
                    + Thread.currentThread() + " status " + newState);

            discoverBluetoothGatt = gatt;

            if (status != BluetoothGatt.GATT_SUCCESS) {
                String err = "Cannot connect device with error status: " + status;
                // 当尝试连接失败的时候调用 disconnect 方法是不会引起这个方法回调的，所以这里
                //   直接回调就可以了。
                gatt.close();
                return;
            }

            if (newState == BluetoothProfile.STATE_CONNECTED) {
                //gatt.discoverServices();
            } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                gatt.close();
            }
        }
    }


    private void readBleData(BluetoothGatt mBluetoothGatt, UUID serviceUuid
            , UUID characteristicUuid, UUID descriptorUuid) {

        //TODO 获得蓝牙设备提供的服务
        BluetoothGattService service = mBluetoothGatt.getService(serviceUuid);

        //TODO 获得服务对应的特征
        BluetoothGattCharacteristic characteristic = service.getCharacteristic(characteristicUuid);

        //TODO 获得特征对应的描述
        BluetoothGattDescriptor descriptor = characteristic.getDescriptor(descriptorUuid);


        //TODO 读取数据  Characteristic中定义了数值
        mBluetoothGatt.readCharacteristic(characteristic);
    }

    /***
     * 写数据
     * @param mBluetoothGatt
     * @param serviceUuid
     * @param characteristicUuid
     * @param sendValue
     */
    private void writeBleData(BluetoothGatt mBluetoothGatt, UUID serviceUuid
            , UUID characteristicUuid, String sendValue) {
        //TODO 获得蓝牙设备提供的服务
        BluetoothGattService service = mBluetoothGatt.getService(serviceUuid);

        //TODO 获得服务对应的特征
        BluetoothGattCharacteristic characteristic = service.getCharacteristic(characteristicUuid);

        characteristic.setValue(sendValue);
        mBluetoothGatt.writeCharacteristic(characteristic);

    }

    private void closeBle() {

    }

}